package com.stox.services.screener.model;

import java.util.List;

import com.stox.services.data.provider.manager.BarManager;
import com.stox.services.data.provider.manager.ScripManager;
import com.stox.services.screener.model.intf.Screen;
import com.stox.services.screener.model.intf.ScreenMatch;
import com.stox.shared.beans.BeanDescriptor;
import com.stox.shared.model.Bar;
import com.stox.shared.model.ScreenBeanDescriptor;
import com.stox.shared.model.ScreenerConfiguration;
import com.stox.shared.model.Scrip;

public abstract class AbstractScreen<T extends BaseScreenConfiguration, V extends ScreenMatch> implements Screen<T> {

	private final String key;
	private ScripManager scripManager;
	private BarManager barManager;
	private final ScreenBeanDescriptor screenBeanDescriptor;
	
	public AbstractScreen(String key, T screenConfiguration, BeanDescriptor screenMatchBeanDescriptor) {
		this.key = key;
		screenBeanDescriptor = new ScreenBeanDescriptor(key, screenConfiguration, screenMatchBeanDescriptor);
	}
	
	@Override
	public ScreenBeanDescriptor getScreenBeanDescriptor() {
		return screenBeanDescriptor;
	}
	
	protected void screen(double span, String scanId, 
			ScreenerConfiguration screenerConfiguration, 
			T screenConfiguration){
		List<Scrip> scrips = scripManager.findByScripCriteria(screenerConfiguration.getScripCriteria());
		Scan<V> scan = new Scan<>(scanId);
		
		for(int index = 0; index < scrips.size() && !scan.isCancelRequested(); index++){
			Scrip scrip = scrips.get(index); 
			int matchSpan = screenerConfiguration.getMatchSpan();
			List<Bar> bars = barManager.findByScripId(
					scrip.getId(), 
					screenerConfiguration.getBarType(), 
					screenerConfiguration.getOffset(), 
					(int)(matchSpan + span));
			if(bars.size() >= matchSpan + span){
				for(int matchSpanIndex = 0; 
						matchSpanIndex < matchSpan && !scan.isCancelRequested(); 
						matchSpanIndex++){
					screen(scrip, bars.subList(matchSpanIndex, (int)(matchSpanIndex + span)), scan, screenConfiguration);
				}
			}
			
			scan.setCompletionPercentage((index+1)*100/scrips.size());
		}
	}
	
	public abstract void screen(Scrip scrip, List<Bar> bars, Scan<V> scan, T screenConfiguration);

	@Override
	public String getKey() {
		return key;
	}
	
	public void setScripManager(ScripManager scripManager) {
		this.scripManager = scripManager;
	}
	
	public void setBarManager(BarManager barManager) {
		this.barManager = barManager;
	}
}
